<?php
//
//$strIncludePath = get_include_path();
//$strPearPath = "D:\\eclipse\\pleiades35jre\\xampp\\php\\PEAR\\";
//set_include_path(get_include_path() . PATH_SEPARATOR . $strPearPath);
//$strIncludePath = get_include_path();

require_once("XML/Unserializer.php");

class Lib_Unserializer extends  XML_Unserializer
{
	/**
	 * 強制配列か指定文字列定数
	 * @var string
	 */
	const FORCE_ENUM_STRUCTURE = "forceEnumStructure";

	/**
	 * 実行済みフラグ
	 * @var boolern
	 */
	protected $_bMeDo = FALSE;

	/**
	 * 強制配列していきー定数
	 * @var string
	 */
	protected $_aryForceEnumStructure;

	/**
	 * コンストラクタ
	 * @param array $aryOptions
	 * @return void
	 */
	public function __construct( $aryOptions="" )
	{
		if ( $aryOptions != "" ) {
			if ( !empty( $aryOptions[self::FORCE_ENUM_STRUCTURE] ) ) {
				unset( $aryOptions["forceEnum"] );
				$this->_bMeDo = TRUE;
				$this->_createForceEnumStructure( $aryOptions[self::FORCE_ENUM_STRUCTURE]);
			}
			parent::__construct( $aryOptions );
		} else {
			parent::__construct();
		}
	}

	/**
	 * アンシリアライズした配列を返す
	 * @return array
	 */
	public function getUnserializedData()
	{
		$aryUnserializedData = parent::getUnserializedData();
		if ( !$this->_bMeDo ) {
			return $aryUnserializedData;
		}

		foreach ( $this->_aryForceEnumStructure as $aryForceEnumStructure ) {
			$aryKeys = $this->_isset_array( $aryUnserializedData, $aryForceEnumStructure[1] );
			if ( $aryKeys == FALSE ) {
				continue;
			}

			$this->_forceEnumStructure( $aryUnserializedData, $aryKeys );
		}

	}

	/**
	 * 強制配列キー指定
	 * @param $arySrc
	 * @param $aryKeys
	 * @return void
	 */
	protected function _forceEnumStructure( &$arySrc, $aryKeys )
	{
		if ( count( $aryKeys ) == 1 ) {
			if ( $aryKeys[0] == "0" ) {
				return;
			}
			if ( !isset( $arySrc[0] ) ) {
				$aryBuff = $arySrc[$aryKeys[0]];
				unset( $arySrc[$aryKeys[0]] );
				$arySrc[$aryKeys[0]][0] = $aryBuff;
				return;
			}
			return;
		}

		if ( $aryKeys[0] == "0") {
			unset( $aryKeys[0] );
			$aryKeys = array_values( $aryKeys );
			foreach ( $arySrc as &$aryResult ) {
				$this->_forceEnumStructure( $aryResult, $aryKeys );
			}
		} else {
			$aryResult = &$arySrc[$aryKeys[0]];
			unset( $aryKeys[0] );
			$aryKeys = array_values( $aryKeys );
			$this->_forceEnumStructure( $aryResult, $aryKeys );
		}
	}

	/**
	 * 強制配列キー配列作成
	 * @param array $aryForceEnumStructreList
	 * @return void
	 */
	protected function _createForceEnumStructure( $aryForceEnumStructreList )
	{
		$aryForceEnumStructure
		= array(
			array(0,"")
		);

		$this->_aryForceEnumStructure = array();

		foreach ( $aryForceEnumStructreList as $strForceEnumStructure ) {
			$aryDivide = explode(",", $strForceEnumStructure );
			$this->_aryForceEnumStructure[]
			= array(
				count( $aryDivide ),
				$aryDivide
			);
		}

		array_multisort( $this->_aryForceEnumStructure, SORT_DESC );
	}

	/**
	 * 多階層配列の構造をチェックする 各階層の反復も配慮する
	 * @param $arySrc　チェックする配列
	 * @param $aryKey　下り階層キー配列
	 * @return array || FALSE
	 * @see array("a"=>array("b"=>array("c"=>""))) にたいし
	 * @see ::isset_array($arySrc, array("a","b","c") );はTRUEを返す
	 * @see 終端が文字列の場合、終端が数字キーの配列であるかの判定はできない。
	 * @see 終端が配列であるかの確認は、isarrayを別途行うこと
	 */
	protected function _isset_array( $arySrc , $aryKey )
	{
		$aryResult = array();
		$aryCheckBuff = $arySrc;
		foreach ( $aryKey as $strKey ) {
			if ( !isset( $aryCheckBuff[$strKey] ) ) {
				return false;
			}
			$aryResult[] = $strKey;
			if ( isset( $aryCheckBuff[$strKey][0] ) ) {
				$aryCheckBuff = $aryCheckBuff[$strKey][0];
				$aryResult[] = 0;
			} else {
				$aryCheckBuff = $aryCheckBuff[$strKey];
			}
		}
		return $aryResult;
	}

}

/*
$aryForceEnumStructure
= array(
	"YEAR",
	"YEAR,MONTH",
	"YEAR,MONTH,DAY"
);
*/

/* テストロジック
$aryUnserializerOptions
=array(
	Lib_Unserializer::FORCE_ENUM_STRUCTURE=>$aryForceEnumStructure
);

$_objUnserializer = new Lib_Unserializer($aryUnserializerOptions);
$strPath = "D:/eclipse/pleiades35jre/work/calender/XML";
$aryCalenderXml = file_get_contents($strPath .'/calender2.xml');
$_objUnserializer->unserialize( $aryCalenderXml );
$_aryCalenderXml = $_objUnserializer->getUnserializedData();
*/